#include <boost/archive/xml_iarchive.hpp>
#include <boost/archive/xml_oarchive.hpp>
#include <fstream>
#include "bebop.hpp"

using namespace std;
using namespace fctr;

class IClassBase {
public : 
	virtual void Identity() const = 0;
};

class CClassTest : public IClassBase {
private:
	int m_nAttribut1;
	string m_sAttribut2;
	char m_cAttribut3;

public:
	CClassTest(){}
	CClassTest(int _1,const string & _2, char _3)
	:m_nAttribut1(_1), m_sAttribut2(_2), m_cAttribut3(_3)
	{}

	void Identity() const {
		cout << "CClassTest" << " " << m_sAttribut2 << endl;
	}

	static void register_class(){
		ClassManager<IClassBase> * manager = 
			ClassManager<IClassBase>::getClassManager();

		manager->registerClass( new Factory3<IClassBase,CClassTest,	int, string, char>("CClassTest") );
		manager->registerMethod( new Method0<IClassBase,CClassTest,void,true>("CClassTest::Identity", &CClassTest::Identity) );

	}

	static void unregister_class(){
		ClassManager<IClassBase> * manager = 
			ClassManager<IClassBase>::getClassManager();

		manager->unRegisterClass( "CClassTest" );
		manager->unRegisterMethod("CClassTest::Identity");
	}

};


class CClassTest2 : public IClassBase {
private:
	int m_nAttribut1;
	string m_sAttribut2;
	char m_cAttribut3;

public:
	CClassTest2(){}

	CClassTest2(int _1,const string & _2, char _3)
	:m_nAttribut1(_1), m_sAttribut2(_2), m_cAttribut3(_3)
	{}

	void Identity() const {
		cout << "CClassTest2" << " " << m_sAttribut2 << endl;
	}

	static void register_class(){
		ClassManager<IClassBase> * manager = 
			ClassManager<IClassBase>::getClassManager();

		manager->registerClass( new Factory3<IClassBase,CClassTest2, int, string, char>("CClassTest2") );
		manager->registerMethod( new Method0<IClassBase,CClassTest2,void,true>("CClassTest2::Identity", &CClassTest2::Identity) );
	}

	static void unregister_class(){
		ClassManager<IClassBase> * manager = 
			ClassManager<IClassBase>::getClassManager();

		manager->unRegisterClass("CClassTest2");
		manager->unRegisterMethod("CClassTest2::Identity");
	}

};

CLASS_REGISTER(CClassTest)
CLASS_REGISTER(CClassTest2)

int main(){
//// TEST CONVERT
	string test = ToString::parse("Bonjour tous le monde");
	int test2 = ToInt::parse("12 je ne sais");
	string test3 = ToString::parse(test);
	cout << test << " " << test2 << endl;
////

	vector<string> arguments;
	arguments.push_back("2");
	arguments.push_back("grouak");
	arguments.push_back("a");

	Param3<int,string,char> p;
	p.param0 = 1;
	p.param1 = "gruik";
	p.param2 = 'e';
	Params * ptrPar = &p; 
	//ParamArray p2;
	//p2.nbInstances = 1;

	/// test factory
	cout << "TEST1" << endl;
	ClassManager<IClassBase> * manager = ClassManager<IClassBase>::getClassManager();
	IClassBase * ptr3 = manager->create("CClassTest2", ptrPar);
	manager->invoke("CClassTest2::Identity", ptr3);
	delete ptr3;
	ptr3 = NULL;

	/// test serialize
	cout << "TEST2" << endl;
	ofstream oss;
	oss.open("test.xml");
	boost::archive::xml_oarchive oar(oss);
	oar << boost::serialization::make_nvp("MyParam",ptrPar);
	oss.close();

	ptrPar = NULL;

	ifstream iss;
	iss.open("test.xml");
	boost::archive::xml_iarchive iar(iss);
	iar >> boost::serialization::make_nvp("MyParam",ptrPar);

	/// test factory
	cout << "TEST3" << endl;
	ptr3 = manager->create("CClassTest", ptrPar);
	manager->invoke("CClassTest::Identity", ptr3);
	delete ptr3;
	ptr3 = NULL;	

	/// test factory
	cout << "TEST4" << endl;
	try {
		ptrPar->parse(arguments);
		ptr3 = manager->create("CClassTest2", ptrPar);
		manager->invoke("CClassTest2::Identity", ptr3);
		delete ptr3;
		ptr3 = NULL;
	} catch (ParamOutOfBoundException oob){
		cout << oob.what() << endl;
	} catch (UnRegisteredClassException reg){
		cout << reg.what() << endl;		
	}

	system("pause");
}
